package com.sfy.mallchat.common.user.service.impl;

import com.sfy.mallchat.common.common.event.UserBlackEvent;
import com.sfy.mallchat.common.common.event.UserRegisterEvent;
import com.sfy.mallchat.common.common.utils.AssertUtil;
import com.sfy.mallchat.common.user.dao.BlackDao;
import com.sfy.mallchat.common.user.dao.ItemConfigDao;
import com.sfy.mallchat.common.user.dao.UserBackpackDao;
import com.sfy.mallchat.common.user.dao.UserDao;
import com.sfy.mallchat.common.user.domain.entity.Black;
import com.sfy.mallchat.common.user.domain.entity.ItemConfig;
import com.sfy.mallchat.common.user.domain.entity.User;
import com.sfy.mallchat.common.user.domain.entity.UserBackpack;
import com.sfy.mallchat.common.user.domain.enums.BlackEnum;
import com.sfy.mallchat.common.user.domain.enums.ItemEnum;
import com.sfy.mallchat.common.user.domain.enums.ItemTypeEnum;
import com.sfy.mallchat.common.user.domain.vo.resp.BadgeResp;
import com.sfy.mallchat.common.user.domain.vo.resp.BlackReq;
import com.sfy.mallchat.common.user.domain.vo.resp.UserInfoResp;
import com.sfy.mallchat.common.user.domain.vo.resp.WearingBadgeReq;
import com.sfy.mallchat.common.user.service.UserService;
import com.sfy.mallchat.common.user.service.adapter.UserAdapter;
import com.sfy.mallchat.common.user.service.cache.ItemCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfiguration;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.annotation.Target;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private UserBackpackDao userBackDao;

    @Autowired
    private ItemCache itemCache;
    @Autowired
    private ItemConfigDao itemConfigDao;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private BlackDao blackDao;


    @Override
    public Long register(User insert) {
        userDao.insert(insert);
        // 用户注册事件
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this, insert));
        return insert.getId();
    }


    @Override
    public UserInfoResp getUserInfo(Long uid) {
        User user = userDao.getById(uid);
        Integer modifyNameCount = userBackDao.getCountByValidItemId(uid, ItemEnum.MODIFY_NAME_CARD.getId());
        return UserAdapter.buildUserInfo(user, modifyNameCount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyName(Long uid, String name) {
        User oldUser = userDao.getByName(name);
        AssertUtil.isEmpty(oldUser, "名字以及被抢占了");
        UserBackpack firstValidItem = userBackDao.getFirstValidItem(uid, ItemEnum.MODIFY_NAME_CARD.getId());
        AssertUtil.isNotEmpty(firstValidItem, "改名卡不足");
        // 更新用户信息
        Boolean isUpdate = userBackDao.userItem(firstValidItem);
        if (isUpdate) {
            userDao.modifyName(uid, name);
        }
    }

    @Override
    public List<BadgeResp> badeges(Long uid) {
        // 查询所有徽章
        List<ItemConfig> itemConfigs = itemCache.getByType(ItemTypeEnum.BADGE.getType());
        // 查询用户的徽章
        List<UserBackpack> backpacks = userBackDao
                .getByItemIds(uid, itemConfigs.stream().map(ItemConfig::getId).collect(Collectors.toList()));
        // 查询用户当钱佩戴的徽章
        User user = userDao.getById(uid);
        return UserAdapter.buildBadgeResp(itemConfigs, backpacks, user);
    }

    /**
     * @param uid
     * @param req
     */
    @Override
    public void wearingBadge(Long uid, WearingBadgeReq req) {
        //确保有这个徽章
        UserBackpack firstValidItem = userBackDao.getFirstValidItem(uid, req.getItemId());
        AssertUtil.isNotEmpty(firstValidItem, "没有该徽章");
        //确保物品类型是徽章
        ItemConfig itemConfig = itemConfigDao.getById(req.getItemId());
        AssertUtil.equal(itemConfig.getType(), ItemTypeEnum.BADGE.getType(), "该徽章不能佩戴");
        //佩戴徽章
        userDao.wearingBadge(uid, req.getItemId());
        //删除用户缓存 TODO
    }


    /**
     * 黑名单
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void black(BlackReq req) {
        Long uid = req.getUid();
        Black user = new Black();
        user.setType(BlackEnum.UID.getType());
        user.setTarget(uid.toString());
        blackDao.save(user);
        User byId = userDao.getById(uid);
        blackIp(byId.getIpInfo().getCreateIp());
        blackIp(byId.getIpInfo().getUpdateIp());
        applicationEventPublisher.publishEvent(new UserBlackEvent(this, byId));
    }

    private void blackIp(String ip) {
        if (StringUtils.isBlank(ip)) {
            return;
        }
        try{
            // 防止getCreateIp和getUpdateIp一样，导致重复拉黑报错
            Black user = new Black();
            user.setType(BlackEnum.IP.getType());
            user.setTarget(ip);
            blackDao.save(user);
        }catch (Exception e){

        }
    }


}
